﻿using System;
using System.Collections.Generic;
using System.Linq;
using Wintellect.Sterling;

namespace Archie.Retail.Data.SterlingStorage
{
    internal class SterlingDataManager<T>
        where T : class, IKeyed, new()
    {
        private const string NotFoundByKey = "Element not found by key";
        private const string EmptyCollection = "Empty collection";

        private readonly ISterlingDatabaseInstance _databaseInstance;

        public SterlingDataManager(ISterlingDatabaseInstance databaseInstance)
        {
            _databaseInstance = databaseInstance;
        }

        private bool CheckElements() 
        {
            return _databaseInstance
                    .Query<T, Guid>()
                    .Any();
        }

        private bool CheckElement(Guid id) 
        {
            return _databaseInstance
                        .Query<T, Guid>()
                        .Any(x=>x.Key == id);
        }

        public IEnumerable<T> GetAll() 
        {
            if (!CheckElements())
            {
                return new T[0];
            }

            var doorManufacturers = _databaseInstance
                                .Query<T, Guid>()
                                .Where(x => x.LazyValue != null)
                                .Select(x => x.LazyValue.Value)
                                .ToArray();

            return doorManufacturers;
        }

        public T Get(Guid id)
        {
            var item = _databaseInstance
                        .Query<T, Guid>()
                        .FirstOrDefault(x => x.Key == id);

            if(item == null)
            {
                return null;
            }

            return item.LazyValue.Value;
        }

        public void Add(T item)
        {
            _databaseInstance.Save(item);
            _databaseInstance.Flush();
        }
        
        public void Update(T editedItem)
        {
            if (!CheckElement(editedItem.Id))
            {
                throw new KeyNotFoundException(NotFoundByKey);
            }
            
            _databaseInstance.Save(editedItem);
            _databaseInstance.Flush();
        }

        public void Delete(Guid id)
        {
            if (!CheckElement(id))
            {
                throw new KeyNotFoundException(NotFoundByKey);
            }

            var deleteCandidate = _databaseInstance
                .Query<T, Guid>()
                .Where(x => x.Key == id)
                .Select(x => x.LazyValue.Value)
                .FirstOrDefault();

            _databaseInstance.Delete(deleteCandidate);
            _databaseInstance.Flush();
        }
    }
}
